from django import forms
from .models import (User, DataOwnership, AuthorizationToken, ResaleRecord)
from django.core.validators import FileExtensionValidator, RegexValidator
from .utils import generate_homomorphic_token, deserialize_encrypted_data, encrypt_token
from phe import paillier


class TokenForm(forms.ModelForm):
    """
    授权令牌表单，用于创建或更新授权令牌
    """
    resale_level = forms.IntegerField(
        label="允许转售级数",
        min_value=1,
        max_value=10,
        initial=3,
        widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '请输入1-10级'})
    )
    valid_days = forms.IntegerField(
        label="有效天数",
        min_value=1,
        max_value=365,
        initial=30,
        widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '请输入1-365天'})
    )

    class Meta:
        model = AuthorizationToken
        fields = ['original_token', 'resale_level', 'valid_days']

    def __init__(self, *args, **kwargs):
        """
        初始化表单，接收用户对象
        :param args: 位置参数
        :param kwargs: 关键字参数，其中包含用户对象
        """
        self.user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)

    def clean_original_token(self):
        """
        验证原始令牌，确保其存在且属于当前用户
        :return: 验证通过的原始令牌
        """
        token = self.cleaned_data['original_token']
        if not self.user:
            raise forms.ValidationError("用户未登录")
        try:
            data_ownership = DataOwnership.objects.filter(owner=self.user, token=token).first()
            if not data_ownership:
                raise forms.ValidationError("该令牌不存在或不属于您")
            public_key_n = data_ownership.public_key
            if not public_key_n:
                raise forms.ValidationError("该令牌无效或未初始化，请重新生成")
            public_key = paillier.PaillierPublicKey(int(public_key_n))
            deserialize_encrypted_data(token, public_key)
            return token
        except (ValueError, SyntaxError, TypeError):
            raise forms.ValidationError("该令牌不存在或不属于您")

    def save(self, commit=True):
        """
        保存授权令牌，生成新的令牌和密钥对
        :param commit: 是否提交到数据库
        :return: 保存后的授权令牌实例
        """
        instance = super().save(commit=False)
        instance.seller = self.user
        token_data = generate_homomorphic_token()
        instance.new_token = token_data['token']
        instance.public_key = str(token_data['public_key'])
        instance.private_key = str(token_data['private_key'])
        if commit:
            instance.save()
        return instance


class TokenVerificationForm(forms.Form):
    """
    令牌验证表单，用于验证令牌的有效性
    """
    token = forms.CharField(
        label="验证令牌",
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入要验证的令牌'})
    )

    def clean_token(self):
        """
        验证令牌，确保其存在且有效
        :return: 验证通过的令牌
        """
        token = self.cleaned_data['token']
        auth_token = AuthorizationToken.objects.filter(new_token=token).first()
        if not auth_token:
            raise forms.ValidationError("无效的令牌")
        public_key_n = auth_token.public_key
        if not public_key_n:
            raise forms.ValidationError("该令牌无效或未初始化，请重新生成")
        public_key = paillier.PaillierPublicKey(int(public_key_n))
        try:
            deserialize_encrypted_data(token, public_key)
            return token
        except Exception:
            raise forms.ValidationError("无效的令牌格式")


class ResaleForm(forms.ModelForm):
    """
    转售记录表单，用于创建或更新转售记录
    """
    valid_days = forms.IntegerField(
        label="规定使用天数",
        min_value=1,
        widget=forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '请输入1-365天'})
    )

    class Meta:
        model = ResaleRecord
        fields = ['buyer_phone', 'valid_days']

    def clean_buyer_phone(self):
        """
        验证买家电话号码，确保其已注册
        :return: 验证通过的买家电话号码
        """
        phone = self.cleaned_data['buyer_phone']
        if not User.objects.filter(phone_number=phone).exists():
            raise forms.ValidationError("买家电话号码未注册")
        return phone

    def save(self, commit=True):
        """
        保存转售记录，生成新的授权令牌和密钥对
        :param commit: 是否提交到数据库
        :return: 保存后的转售记录实例
        """
        instance = super().save(commit=False)
        token_data = generate_homomorphic_token()
        instance.new_authorization_token = token_data['token']
        instance.public_key = str(token_data['public_key'])
        instance.private_key = str(token_data['private_key'])
        if commit:
            instance.save()
        return instance


class UserRegistrationForm(forms.ModelForm):
    """
    用户注册表单，用于创建新用户
    """
    password1 = forms.CharField(label="密码", widget=forms.PasswordInput)
    password2 = forms.CharField(label="再次输入密码", widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ["phone_number", "id_card"]

    def clean_password2(self):
        """
        验证两次输入的密码是否一致
        :return: 验证通过的第二次输入的密码
        """
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("两次输入的密码不一致")
        return password2

    def save(self, commit=True):
        """
        保存用户，设置密码并保存到数据库
        :param commit: 是否提交到数据库
        :return: 保存后的用户实例
        """
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserLoginForm(forms.Form):
    """
    用户登录表单，用于用户登录
    """
    phone_number = forms.CharField(label="电话号码")
    password = forms.CharField(label="密码", widget=forms.PasswordInput)


class DataUploadForm(forms.Form):
    """
    数据上传表单，用于用户上传数据
    """
    # 新增 data_name 字段（与前端 name="data_name" 对应）
    data_name = forms.CharField(
        max_length=255,
        label='数据名称',
        widget=forms.TextInput(
            attrs={'class': 'mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm'})
    )

    # 新增 data_description 字段（与前端 name="data_description" 对应）
    data_description = forms.CharField(
        label='数据描述',
        widget=forms.Textarea(
            attrs={'class': 'mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm'}),
        required=False  # 根据需求设置是否必填
    )

    data_file = forms.FileField(
        validators=[FileExtensionValidator(allowed_extensions=['csv', 'json', 'txt', 'xlsx', 'pdf', 'docx'])],
        label='选择文件'
    )

    # 保留电话号码字段（如果有）
    phone_number = forms.CharField(
        max_length=11,
        widget=forms.HiddenInput(),
        validators=[RegexValidator(regex=r'^1[3-9]\d{9}$', message="电话号码格式错误")],  # 修改为直接使用 RegexValidator
        required=True
    )